package Bio::Rambam::Proteomics::Formats::OmssaFile;
use namespace::autoclean;
use Moose;
use Data::Dumper;
use Bio::Rambam::Proteomics::old::Peptide;
use Bio::Rambam::Proteomics::old::Score;
use Bio::Rambam::Proteomics::old::Modification;
use Bio::Rambam::Proteomics::old::Protein;
use Bio::Rambam::Proteomics::old::Psm;

has 'file'				=>	(is=>'rw',isa=>'Str');



sub parse{
	my %omssa_report_data_structure;
	my $self=shift;
	open my $fh, $self->file or die "$self->file: $!";
	my $field = qr/"(?:[^"\\]|\\.)*"|[^"\\,]*/s;
	my @peptides;
	my %proteins;
	
	while (<$fh>) {
		chomp;
		next if /^Spectrum number\,/;
		my ($spectrum_number,$filename_id,$peptide,$e_value,$mass,$defline,$mods,$charge,$theo_mass,$p_value) =
			/^($field),($field),($field),($field),($field),$field,$field,$field,$field,($field),($field),($field),($field),($field),$field/
			  or die;
		my %line_data=('spectrum_number',$spectrum_number,'filename_id',$filename_id,'peptide',$peptide,'e_value',$e_value,
			'mass',$mass,'defline',$defline,'mods',$mods,'charge',$charge,'theo_mass',$theo_mass,'p_value',$p_value);
		
		#Peptide
		my $peptide_sequence=$peptide;
		$peptide_sequence =~ tr/[a-z]/[A-Z]/;
		my $peptide_obj=Bio::Rambam::Proteomics::Peptide->new(identifier=>$filename_id,sequence=>$peptide_sequence,charge=>$charge);
		#Scores
		$e_value=1*$e_value;
		$p_value=1*$p_value;
		$peptide_obj->set_score(name=>'omssa_evalue',value=>$e_value);
		$peptide_obj->set_score(name=>'omssa_pvalue',value=>$p_value);
		# Modifications
		my @mods=split / \,/,$mods;
		foreach my $mod(@mods){
			my $mass;
			my $location='';
			$mass=144.1	if $mod=~/iTRAQ/;
			$mass=16.0	if $mod=~/oxidation/;
			$mass=42.0	if $mod=~/acetylation/;
			$mass=229.16 if $mod=~/TMT/;
			$location=0 if $mod=~/nterm/;
			$location=(1+(length($peptide))) if $mod=~/cterm/;
			if($location eq ''){
				$mod=~/\:(\d+)/;
				$location=$1;
			}
			$peptide_obj->set_modification(modLocation	=> $location, modmonodelta=> $mass);
		}
		# Modifications -> implicit CAM at C
		my $pos=0;
		foreach(split //,$peptide_sequence){
			$pos++;
			if(/C/){
				$peptide_obj->set_modification(modLocation	=> $pos, modmonodelta=> 57.0);
			}
		}
		push @{$omssa_report_data_structure{$filename_id}{$peptide}{$peptide_obj->modifications_string}{'proteins'}},$defline;
		if((abs($theo_mass-$peptide_obj->calculate_molecular_mass))>=0.1){
			print "\tWrong modification :\n\t\t",$filename_id,"\n\t\t",$peptide_obj->sequence,"\n\t\t",($peptide_obj->calculate_molecular_mass),"\|",$theo_mass,"\n\t\t",$peptide_obj->modifications_string,"\n";
			next;
		}

		$omssa_report_data_structure{$filename_id}{$peptide}{$peptide_obj->modifications_string}{'peptide_obj'}=$peptide_obj;
		
	}
	
		
	my %unique_result_peptide_list;	#only the best (or the first best) e-valued peptide will go to the report
	
	id:foreach my $id(keys %omssa_report_data_structure){
		foreach my $seq(keys %{$omssa_report_data_structure{$id}}){
			foreach my $mods(keys %{$omssa_report_data_structure{$id}{$seq}}){
					my @proteins_list=@{$omssa_report_data_structure{$id}{$seq}{$mods}{'proteins'}};
					my $peptide_obj=$omssa_report_data_structure{$id}{$seq}{$mods}{'peptide_obj'};
					next id unless defined $peptide_obj;
					my %unique_prot_list;
					foreach my $prot(@proteins_list){
						my ($origin,$accession,$name)=split /\|/,$prot;
						$name="" unless defined $name;
						next if defined $unique_prot_list{$accession};
						$unique_prot_list{$accession}=1;
						unless (defined $accession and defined $origin and defined $name){
							print "Protein not defined properly\n";
							print $prot;exit;
						};
						$origin=~s/\"//g;
						my $decoy=0;
						$decoy=1 if $origin eq "dc";
						my $protein=Bio::Rambam::Proteomics::Protein->new(accession=>$accession,origin=>$origin,name=>$name,decoy=>$decoy);
						$proteins{$accession}=$protein;
						$peptide_obj->set_protein($accession);
					}
					my @scores=$peptide_obj->get_scores;
					my $evalue='';
					foreach my $score(@scores){
						$evalue=$score->value if $score->name eq 'omssa_evalue';
					}
					unless(defined $unique_result_peptide_list{$peptide_obj->identifier}){
						$unique_result_peptide_list{$peptide_obj->identifier}{'peptide'}=$peptide_obj;
						$unique_result_peptide_list{$peptide_obj->identifier}{'evalue'}=$evalue;
					}
					else{
						if($evalue<$unique_result_peptide_list{$peptide_obj->identifier}{'evalue'}){
							$unique_result_peptide_list{$peptide_obj->identifier}{'peptide'}=$peptide_obj;
							$unique_result_peptide_list{$peptide_obj->identifier}{'evalue'}=$evalue;
						}
					}
			}
		}
	}
	
	foreach my $id(sort keys %unique_result_peptide_list){
		my $peptide=$unique_result_peptide_list{$id}{'peptide'};
		my @prots_in_peptide=@{$peptide->protein_accessions};
		my $decoy=0;
		foreach my $prot(@prots_in_peptide){
			$decoy=1 if $prot=~/^d/;
		}
		$peptide->decoy_peptide($decoy);
		push @peptides, $peptide;
		#$self->set_peptide($unique_result_peptide_list{$id}{'peptide'});
	}
	#foreach my $prot(keys %proteins){
		
	#	$self->set_protein($proteins{$prot});
	#}
	#print "kk\n" foreach @peptides;
	#print Dumper @peptides;
	return (\@peptides,\%proteins);
}


















__PACKAGE__->meta->make_immutable;
